iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Software Development

從零開始學 Python系列 第 18

Day 18 – with open: 讀寫檔案

  • 分享至 

  • xImage
  •  

今天的學習重點

  • 為什麼要讀寫檔案?
  • open() 的用法與模式 (r, w, a, x)
  • 檔案的讀取方法:read()、readline()、readlines()
  • 檔案的寫入與追加

一、為什麼要讀寫檔案?

到目前為止我的程式大多只能輸入輸出在「螢幕」上,但現實應用中常常需要存下程式運算的結果(例如紀錄日誌、存成文字檔)、從檔案中讀取資料(例如 CSV、文字檔、設定檔)。所以檔案 I/O(Input/Output)就是程式能夠與外部世界互動的關鍵!

二、open() 的基本語法

f = open("data.txt", "r")  # 開啟檔案
# ...操作...
f.close()                  # 關閉檔案

模式 (mode) 說明:

  • "r" → 讀取模式(檔案不存在會報錯)
  • "w" → 寫入模式(會覆蓋原檔案!)
  • "a" → 追加模式(內容加到檔案尾端)
  • "x" → 建立新檔案(檔案已存在會報錯)

1) "r" 讀取(檔案必須存在)

with open("data.txt", "r", encoding="utf-8") as f:
    print(f.read())
  • f.read() 第一次會把檔案整個讀掉,指標跑到檔尾。
  • 如果不移動,下一次 read() 就什麼都不會輸出。
  • 不存在會 FileNotFoundError

2) "w" 覆蓋寫入(會清空舊檔)

with open("out.txt", "w", encoding="utf-8") as f:
    f.write("重新開始寫入\n")
  • 舊內容會被清空。要保留請用 "a" 或先備份。

3) "a" 追加寫入(不清空)

with open("log.txt", "a", encoding="utf-8") as f:
    f.write("追加一行\n")
  • 不存在會自動建立
  • 寫入永遠在檔尾(就算 seek(0),寫還是會到尾端)

甚麼是seek
在 Python 中,檔案物件(file object)有一個「檔案指標」(file pointer),它決定了你下一次讀或寫的位置。
seek(offset, whence=0) 就是用來移動檔案指標的方法。

  • offset:移動的距離(單位:位元組 bytes)
  • whence:參考點(預設是 0)
  • 0 → 從檔案開頭算(default)
  • 1 → 從目前位置算
  • 2 → 從檔案尾端算

4) "x" 僅新建(已存在就報錯)

try:
    with open("unique.txt", "x", encoding="utf-8") as f:
        f.write("只在不存在時建立\n")
except FileExistsError:
    print("檔案已存在,安全取消!")
  • 用於「保證不覆蓋」的場景(例如輸出結果檔)

5) "r+" 讀寫(不清空,指標在檔頭)

with open("doc.txt", "r+", encoding="utf-8") as f:
    old = f.read()
    f.seek(0)
    f.write("前綴\n" + old)
  • 不存在會噴錯
  • 適合「在前面加內容」這種操作(搭配 seek)

6) "w+" 清空後讀寫

with open("doc.txt", "w+", encoding="utf-8") as f:
    f.write("新內容\n")
    f.seek(0)
    print(f.read())  # 可讀,但舊內容已清空

7) "a+" 讀寫(不清空,寫入在尾端)

with open("doc.txt", "a+", encoding="utf-8") as f:
    f.write("尾端追加\n")
    f.seek(0)
    print(f.read())

三、with open 的好處

手動 open() / close() 很容易忘記關閉檔案,造成檔案被鎖住。
所以 Python 提供了 with open 語法:

with open("data.txt", "r") as f:
    content = f.read()
    print(content)   # 自動關閉檔案

with 區塊結束後,檔案會自動關閉,不用再寫 f.close()。

四、讀取檔案的方法

with open("data.txt", "r") as f:
    print("read():")
    print(f.read())               # 讀取整個檔案內容

with open("data.txt", "r") as f:
    print("readline():")
    print(f.readline())           # 讀取一行

with open("data.txt", "r") as f:
    print("readlines():")
    print(f.readlines())          # 讀取所有行,回傳 list

五、寫入與追加

# 覆蓋寫入
with open("output.txt", "w") as f:
    f.write("Hello, file!\n")

# 追加模式
with open("output.txt", "a") as f:
    f.write("Add another line!\n")

執行後,output.txt 的內容會隨著模式不同而更新。

六、綜合小練習:簡易日誌系統

import datetime

log = f"{datetime.datetime.now()}: 程式執行成功\n"

with open("log.txt", "a", encoding="utf-8") as f:
    f.write(log)

print("日誌已更新!")

螢幕擷取畫面 2025-08-20 132431
螢幕擷取畫面 2025-08-20 132747
每次執行,log.txt 會新增一行記錄。

常用參數補充:

  • encoding="utf-8":文字檔一致用 UTF-8,跨平台少踩雷。
  • newline="":寫入時不自動轉換換行符號(適合處理 CSV)。
  • errors="ignore":遇無法解碼的字元時忽略(或用 "replace" 置換)。
  • buffering=1:行緩衝;大檔案可調整以優化效能。
  • pathlib.Path:路徑好用工具。
from pathlib import Path
p = Path("data") / "out.txt"
with p.open("a", encoding="utf-8") as f:
    f.write("hi\n")

筆記

  • 只讀:"r"
  • 重產生(清空舊檔):"w"
  • 在尾巴追加:"a"
  • 要保證不覆蓋:"x"
  • 邊讀邊改:"r+"(或 "a+" 讀舊+尾端加新)
  • 圖片/檔案位元組:加 "b" → "rb", "wb", "ab"

搭配 try/except 的安全寫法

try:
    with open("maybe.txt", "r", encoding="utf-8") as f:
        data = f.read()
except FileNotFoundError:
    data = ""  # 或者給提示訊息

學習心得

今天學了 檔案的讀寫操作,能讓程式「留下痕跡」,不再只是輸出到螢幕。我覺得有點複雜!
明天要學習模組化專案結構,包括如何將程式拆成多個檔案、如何匯入自訂模組,開始體驗「專案架構」的規劃!


上一篇
Day 17 – try / except 例外處理:讓程式更穩健
下一篇
Day 19 – 自訂模組與簡單封裝
系列文
從零開始學 Python30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言